package edu.cicese.alz.reports;

import edu.cicese.alz.SwingComponent;
import edu.cicese.alz.swing.SwingUtil;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.LookupPaintScale;
import org.jfree.chart.title.PaintScaleLegend;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;

import javax.swing.DefaultListModel;
import java.awt.Color;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 6/08/12
 * Time: 02:14 PM
 */
public class FrameCombinedBlock extends SwingComponent {

	private int[] opacities;

	private int days;
	private DefaultXYZDataset[] xyzDatasets;
	private DateAxis[] yAxes, xAxes;
	private CustomXYBlockRenderer renderers[];
	private LookupPaintScale[] paintScales;
	private SymbolAxis[] symbolAxes;
	private PaintScaleLegend[] paintScaleLegends;

	private int layers;
	private int zAccelerometer, zNFC, zGPS;

	public FrameCombinedBlock(int days, DefaultListModel layers, int[] opacities) {
		this.days = days;
		this.layers = layers.size();
		this.opacities = opacities;

		for (int i = 0; i < this.layers; i++) {
			switch ((String) layers.get(i)) {
				case "Accelerometer":
					zAccelerometer = i;
					break;
				case "GPS":
					zGPS = i;
					break;
				case "NFC":
					zNFC = i;
					break;
			}
		}

		xyzDatasets = new DefaultXYZDataset[this.layers];
		paintScales = new LookupPaintScale[this.layers];
		symbolAxes = new SymbolAxis[this.layers];
	}


	public void setAccelerometerData(double[][] accelerometerValues, Color colorNoDataAccelerometer, Color colorNoMovement,
	                                 Color colorSedentary, Color colorLight, Color colorModerate, Color colorHard) {
		xyzDatasets[zAccelerometer] = new DefaultXYZDataset();
		xyzDatasets[zAccelerometer].addSeries("Series Accelerometer", accelerometerValues);

		// Set paint scale and symbols
		paintScales[zAccelerometer] = new LookupPaintScale(0.5, 6.5, colorNoDataAccelerometer);
		paintScales[zAccelerometer].add(0.5, SwingUtil.getTransparentColor(colorNoDataAccelerometer, opacities[0]));
		paintScales[zAccelerometer].add(1.5, SwingUtil.getTransparentColor(colorNoMovement, opacities[1]));
		paintScales[zAccelerometer].add(2.5, SwingUtil.getTransparentColor(colorSedentary, opacities[1]));
		paintScales[zAccelerometer].add(3.5, SwingUtil.getTransparentColor(colorLight, opacities[1]));
		paintScales[zAccelerometer].add(4.5, SwingUtil.getTransparentColor(colorModerate, opacities[1]));
		paintScales[zAccelerometer].add(5.5, SwingUtil.getTransparentColor(colorHard, opacities[1]));

		setSymbolAxis(zAccelerometer, new String[]{"", "No Data", "No Movement", "Sedentary", "Light", "Moderate", "Hard"}, 6.5);
	}

	public void setNFCData(double[][] nfcValues, List<NFCTag> nfcTags, Color colorNoDataNFC) {
		xyzDatasets[zNFC] = new DefaultXYZDataset();
		xyzDatasets[zNFC].addSeries("Series NFC", nfcValues);

		// Set paint scale and symbols
		paintScales[zNFC] = new LookupPaintScale(0.5, nfcTags.size() + 1.5, colorNoDataNFC);
		paintScales[zNFC].add(0.5, SwingUtil.getTransparentColor(colorNoDataNFC, opacities[5]));
		String[] symbols = new String[nfcTags.size() + 2];
		symbols[0] = "";
		symbols[1] = "No Data";
		for (int i = 0; i < nfcTags.size(); i++) {
			paintScales[zNFC].add(i + 1.5, SwingUtil.getTransparentColor(nfcTags.get(i).getColor(), opacities[6]));
			symbols[i + 2] = nfcTags.get(i).getProfileCheckBox().getText();
		}

		setSymbolAxis(zNFC, symbols, nfcTags.size() + 1.5);
	}

	public void setGPSData(double[][] gpsValues, Color colorNoDataGPS, Color colorHome, Color colorOut) {
		xyzDatasets[zGPS] = new DefaultXYZDataset();
		xyzDatasets[zGPS].addSeries("Series GPS", gpsValues);

		// Set paint scale and symbols
		paintScales[zGPS] = new LookupPaintScale(0.5, 3.5, colorNoDataGPS);
		paintScales[zGPS].add(0.5, SwingUtil.getTransparentColor(colorNoDataGPS, opacities[2]));
		paintScales[zGPS].add(1.5, SwingUtil.getTransparentColor(colorHome, opacities[3]));
		paintScales[zGPS].add(2.5, SwingUtil.getTransparentColor(colorOut, opacities[4]));

		setSymbolAxis(zGPS, new String[]{"", "No Data", "Home", "Out"}, 3.5);
	}

	private void setSymbolAxis(int index, String[] symbols, double range) {
		symbolAxes[index] = new SymbolAxis(null, symbols);
		symbolAxes[index].setRange(0.5, range);
		symbolAxes[index].setPlot(new PiePlot());
		symbolAxes[index].setGridBandsVisible(false);
	}

	
	public void plotData() {
		ChartPanel chartPanel = new ChartPanel(createChart());
		chartPanel.setPreferredSize(new Dimension(1190, 208 + (days * 21)));
		setContentPane(chartPanel);
	}

	private JFreeChart createChart() {
		SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy/MM/dd");
		SimpleDateFormat sdfHour = new SimpleDateFormat("HH:mm");
		sdfHour.setTimeZone(TimeZone.getTimeZone("GMT"));

		yAxes = new DateAxis[layers];
		xAxes = new DateAxis[layers];
		renderers = new CustomXYBlockRenderer[layers];
		paintScaleLegends = new PaintScaleLegend[layers];

		XYPlot plot = new XYPlot();
		JFreeChart chart = new JFreeChart("Multi Dataset Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
		chart.removeLegend();

		for (int i = 0; i < layers; i++) {
			yAxes[i] = new DateAxis("Date");
			yAxes[i].setTickMarkPosition(DateTickMarkPosition.START);
			yAxes[i].setDateFormatOverride(sdfDay);
			yAxes[i].setLowerMargin(0.0D);
			yAxes[i].setUpperMargin(0.0D);
			yAxes[i].setInverted(true);

			xAxes[i] = new DateAxis("Date");
			xAxes[i].setDateFormatOverride(sdfHour);
			xAxes[i].setLowerMargin(0.0D);
			xAxes[i].setUpperMargin(0.0D);

			renderers[i] = new CustomXYBlockRenderer();
			renderers[i].setBlockStroke(null);
			renderers[i].setBlockWidth(86400000.0D);
			renderers[i].setBlockHeight(60000.0D);
			renderers[i].setBlockAnchor(RectangleAnchor.BOTTOM_LEFT);
			renderers[i].setPaintScale(paintScales[i]);

			plot.setDataset(i, xyzDatasets[i]);
			plot.setRenderer(i, renderers[i]);
			plot.setDomainAxis(i, yAxes[i]);
			plot.setRangeAxis(i, xAxes[i]);

			plot.mapDatasetToDomainAxis(i, i);
			plot.mapDatasetToRangeAxis(i, i);

			paintScaleLegends[i] = new PaintScaleLegend(paintScales[i], symbolAxes[i]);
			paintScaleLegends[i].setMargin(new RectangleInsets(3.0D, 10.0D, 3.0D, 10.0D));
			paintScaleLegends[i].setPosition(RectangleEdge.BOTTOM);
			paintScaleLegends[i].setAxisOffset(5.0D);

			chart.addSubtitle(paintScaleLegends[i]);
		}

		plot.setRangeGridlinesVisible(false);
		plot.setOrientation(PlotOrientation.HORIZONTAL);
		plot.setAxisOffset(new RectangleInsets(5.0D, 5.0D, 5.0D, 5.0D));

		try {
			ChartUtilities.saveChartAsPNG(new File("C:\\Users\\Eduardo\\Documents\\" + System.currentTimeMillis() + ".png"), chart, 1190, 208 + (days * 21));
		} catch (IOException e) {
			e.printStackTrace();
		}

		return chart;
	}
}
